import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(
        title: Text("标题"),
      ),
      //body:MyHomeBodyStack(),
      //body: MyHomeBodyColumn(),
      //body: CenterColumnRoute(),
      //body: ColumnInColumn(),
      //body:ColumnInColumn3()
      //body: FlexLayoutTestRoute(),
      //body: WrapTest(),
      //body: TestFlow(),
      //body: StackTest2(),
      //body: AlignTest(),
body: FractionalOffsetTest(),
    ));
  }
}

class TestFlow extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Flow(
      delegate: TestFlowDeletgate(margin: EdgeInsets.all(10.0)),
      children: [
        new Container(width: 80.0, height: 80.0, color: Colors.red),
        new Container(width: 80.0, height: 80.0, color: Colors.green),
        new Container(width: 80.0, height: 80.0, color: Colors.blue),
        new Container(width: 80.0, height: 80.0, color: Colors.yellow),
        new Container(width: 80.0, height: 80.0, color: Colors.brown),
        new Container(width: 80.0, height: 80.0, color: Colors.purple),
      ],
    );
  }
}

class FractionalOffsetTest extends StatelessWidget {
  
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(

      height:120.0,
      width:120.0,
      color:Colors.red[50],
      child:Align(
        alignment: FractionalOffset(0.2,0.6),
        child:FlutterLogo(size: 60)
      )
    );
  }
  }
class AlignTest extends StatelessWidget {
  
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(

      height:120.0,
      width:120.0,
      color:Colors.red[50],
      child:Align(
        alignment:Alignment.topRight,
        child:FlutterLogo(size: 60)
      )
    );
  }
  }

/**
 * 测试Stack
 */
class StackTest2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return ConstrainedBox(
      constraints: BoxConstraints.expand(),
      child: Stack(
        alignment: Alignment.center, 
        //未定位Widget占满Stack的整个空间
        fit: StackFit.expand,
        children: <Widget>[
          //由于Stack子元素是堆叠的，所以第一个子文本组件被第二个遮住了，而第三个在最上层，所以可以正常显示
          Positioned(child: Text("I am Jack"), left: 18.0),
          //由于第二个子文本组件没有定位，所以fit属性会对他起作用，会占满Stack
        Container(
            child: Text("Hello World", style: TextStyle(color: Colors.white)),
            color: Colors.red),
        
        Positioned(child: Text("Your friend"), top: 18.0),
      ]),
    );
  }
}
/**
 * 测试Stack
 */
class StackTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return ConstrainedBox(
      constraints: BoxConstraints.expand(),
      child: Stack(
        alignment: Alignment.center, 
       
        children: <Widget>[
        Container(
            child: Text("Hello World", style: TextStyle(color: Colors.white)),
            color: Colors.red),
        Positioned(child: Text("I am Jack"), left: 18.0),
        Positioned(child: Text("Your friend"), top: 18.0),
      ]),
    );
  }
}

class TestFlowDeletgate extends FlowDelegate {
  EdgeInsets margin = EdgeInsets.zero;

  TestFlowDeletgate({this.margin});
/**
 * 确定每个子Widget的位置
 */
  @override
  void paintChildren(FlowPaintingContext context) {
    var x = margin.left;
    var y = margin.top;

//计算一个子Widget的位置
    for (int i = 0; i < context.childCount; i++) {
      var w = context.getChildSize(i).width + x + margin.right;
      if (w < context.size.width) {
        context.paintChild(i,
            transform: new Matrix4.translationValues(x, y, 0.0));
        x = w + margin.left;
      } else {
        x = margin.left;
        y += context.getChildSize(i).height + margin.top + margin.bottom;

        context.paintChild(i,
            transform: new Matrix4.translationValues(x, y, 0.0));

        x += context.getChildSize(i).width + margin.left + margin.right;
      }
    }
  }

/**
 * 由于Flow不能自适应子Widget的大小，因为我们通过在getSize返回一个固定的大小来指定Flow的大小
 */
  @override
  getSize(BoxConstraints constraints) {
//指定Flow的大小
    return Size(double.infinity, 200.0);
  }

  @override
  shouldRepaint(FlowDelegate oldDelegate) {
    return oldDelegate != this;
  }
}

class WrapTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //Wrap会换行
    return Wrap(
      spacing: 8.0,
      runSpacing: 4.0,
      alignment: WrapAlignment.center,
      children: <Widget>[
        new Chip(
          label: new Text("Hamilton"),
          avatar:
              new CircleAvatar(backgroundColor: Colors.blue, child: Text("A")),
        ),
        new Chip(
          label: new Text("lafayette"),
          avatar:
              new CircleAvatar(backgroundColor: Colors.blue, child: Text("M")),
        ),
        new Chip(
          label: new Text("Mulligan"),
          avatar:
              new CircleAvatar(backgroundColor: Colors.blue, child: Text("H")),
        ),
        new Chip(
          label: new Text("Laurens"),
          avatar:
              new CircleAvatar(backgroundColor: Colors.blue, child: Text("J")),
        )
      ],
    );
  }
}

class FlexLayoutTestRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Flex(
          direction: Axis.horizontal,
          children: <Widget>[
            Expanded(
              child: Container(height: 30.0, color: Colors.red),
              flex: 1,
            ),
            Expanded(
              child: Container(height: 30.0, color: Colors.green),
              flex: 2,
            )
          ],
        ),
        Padding(
          padding: const EdgeInsets.only(top: 20.0),
          child: SizedBox(
              height: 100.0,
              child: Flex(direction: Axis.vertical, children: <Widget>[
                Expanded(
                    flex: 5,
                    child: Container(
                      height: 130.0,
                      color: Colors.red,
                    )),
                //Spacer：占用指定比例的空间
                Spacer(flex: 1),
                Expanded(
                    flex: 1,
                    child: Container(
                      height: 130.0,
                      color: Colors.green,
                    )),
              ])),
        )
      ],
    );
  }
}

/**
 * 这里我们特别解释一下widthFactor和heightFactor作用：
因为子组件在父组件中的对齐方式必须有一个前提，就是父组件得知道自己的范围（宽度和高度）；
如果widthFactor和heightFactor不设置，那么默认Align会尽可能的大（尽可能占据自己所在的父组件）；
我们也可以对他们进行设置，比如widthFactor设置为3，那么相对于Align的宽度是子组件跨度的3倍；
 * 
 */
class MyHomeBodyAlign extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Align(
      child: Icon(
        Icons.pets,
        size: 16,
        color: Colors.red,
      ),
      alignment: Alignment.bottomRight,
      widthFactor: 3,
      heightFactor: 3,
    );
  }
}

/**
 * 
 * 事实上Center组件继承自Align，只是将alignment设置为Alignment.center。
 */
class MyHomeBodyCenter extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Icon(Icons.pets, size: 36, color: Colors.red),
      widthFactor: 3,
      heightFactor: 3,
    );
  }
}

/**
 * Padding组件在其他端也是一个属性而已，但是在Flutter中是一个Widget，但是Flutter中没有Margin这样一个Widget，这是因为外边距也可以通过Padding来完成。
Padding通常用于设置子Widget到父Widget的边距（你可以称之为是父组件的内边距或子Widget的外边距）。
 * 
 * 
 */

class MyHomeBodyPadding extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(20),
      child: Text(
        "莫听穿林打叶声，何妨吟啸且徐行。竹杖芒鞋轻胜马，谁怕？一蓑烟雨任平生。",
        style: TextStyle(color: Colors.redAccent, fontSize: 18),
      ),
    );
  }
}

/**
 * Container在开发中被使用的频率是非常高的，特别是我们经常会将其作为容器组件。
 * 大多数属性在介绍其它容器时都已经介绍过了，不再赘述，但有两点需要说明：
容器的大小可以通过width、height属性来指定，也可以通过constraints来指定，如果同时存在时，width、height优先。实际上Container内部会根据width、height来生成一个constraints；
color和decoration是互斥的，实际上，当指定color时，Container内会自动创建一个decoration；
 * 
 */

class MyHomeBodyContainer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Color.fromRGBO(3, 3, 255, .5),
        width: 100,
        height: 100,
        child: Icon(Icons.pets, size: 32, color: Colors.white),
      ),
    );
  }
}

/**
 * Container有一个非常重要的属性 decoration：
他对应的类型是Decoration类型，但是它是一个抽象类。
在开发中，我们经常使用它的实现类BoxDecoration来进行实例化。
 */

class MyHomeBodyBoxDecoration extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
//        color: Color.fromRGBO(3, 3, 255, .5),
        width: 150,
        height: 150,
        child: Icon(Icons.pets, size: 32, color: Colors.white),
        decoration: BoxDecoration(
            color: Colors.amber, // 背景颜色
            border: Border.all(
                color: Colors.redAccent,
                width: 3,
                style: BorderStyle.solid), // 这里也可以使用Border.all统一设置
//            top: BorderSide(
//              color: Colors.redAccent,
//              width: 3,
//              style: BorderStyle.solid
//            ),
            borderRadius: BorderRadius.circular(20), // 这里也可以使用.only分别设置
            boxShadow: [
              BoxShadow(
                  offset: Offset(5, 5), color: Colors.purple, blurRadius: 5)
            ],
//          shape: BoxShape.circle, // 会和borderRadius冲突
            gradient: LinearGradient(colors: [Colors.green, Colors.red])),
      ),
    );
  }
}

/**
 * 圆角头像
 * 可以通过 Container+BoxDecoration来实现圆角图像
 */
class HomeContentRadiusPhoto extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        width: 200,
        height: 200,
        decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(20),
            image: DecorationImage(
              image: NetworkImage(
                  "https://tva1.sinaimg.cn/large/006y8mN6gy1g7aa03bmfpj3069069mx8.jpg"),
            )),
      ),
    );
  }
}

class MyHomeBodyRow extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      crossAxisAlignment: CrossAxisAlignment.end,
      /**
        * 默认情况下，Row会尽可能占据多的宽度，让子Widget在其中进行排布，这是因为mainAxisSize属性默认值是MainAxisSize.max。
        */
      mainAxisSize: MainAxisSize.max,
      children: <Widget>[
        //Container(color: Colors.red, width: 60, height: 60),
        Expanded(
          //flex属性，弹性系数，Row会根据两个Expanded的弹性系数来决定它们占据剩下空间的比例
          flex: 1,
          child: Container(color: Colors.red, height: 60),
        ),
        Container(color: Colors.blue, width: 80, height: 80),
        Container(color: Colors.green, width: 70, height: 70),
        //Container(color: Colors.orange, width: 100, height: 100),
        Expanded(
          flex: 1,
          child: Container(color: Colors.orange, height: 100),
        )
      ],
    );
  }
}

class CenterColumnRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Text("hi"),
        Text("hello"),
      ],
    );
  }
}

class ColumnInColumn extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.green,
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.max,
            children: <Widget>[
              Container(
                  color: Colors.red,
                  child: Column(
                      mainAxisSize: MainAxisSize.max,
                      children: <Widget>[
                        Text("hello world"),
                        Text("I am jack")
                      ]))
            ]),
      ),
    );
  }
}

class ColumnInColumn2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Container(
          color: Colors.red,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[Text("hello world"), Text("I am jack")],
          )),
    );
  }
}

class ColumnInColumn3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.green,
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.max,
            children: <Widget>[
              Expanded(
                  child: Container(
                      color: Colors.red,
                      child: Column(
                          mainAxisSize: MainAxisSize.max,
                          children: <Widget>[
                            Text("hello world"),
                            Text("I am jack")
                          ])))
            ]),
      ),
    );
  }
}

/**
 * Column组件用于将所有的子Widget排成一列，学会了前面的Row后，Column只是和row的方向不同而已。
 */
class MyHomeBodyColumn extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      //mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      crossAxisAlignment: CrossAxisAlignment.start,
      //mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        //居中对齐
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[Text(" hello world "), Text(" I am yuexiaowei ")],
        ),

        //由于mainAxisSize的值为MainAxisSize.min，Row的宽度等于两个Text的宽度和，所以对齐是无意义的，因此会从左往右显示
        Row(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[Text(" hello world "), Text(" I am yuexiaowei ")],
        ),

        //由于textDirection:的值为TextDirection.rtl，所以子组件会以从右向左的顺序排列
        //而此时MainAxisAlignment.end表示左对齐，
        Row(
          mainAxisAlignment: MainAxisAlignment.end,
          textDirection: TextDirection.rtl,
          children: <Widget>[Text(" hello world "), Text(" I am yuexiaowei ")],
        ),

        //测试的是纵轴的对齐方式，由于两个Text的字体不一样，所以其高度也不同，MainAxisAlignment.start表示底对齐
        Row(
          mainAxisAlignment: MainAxisAlignment.start,
          verticalDirection: VerticalDirection.up,
          children: <Widget>[
            Text(
              " hello world ",
              style: TextStyle(fontSize: 30.0),
            ),
            Text(" I am yuexiaowei ")
          ],
        ),
        //下边两个显示效果是一样的
        Row(
          mainAxisAlignment: MainAxisAlignment.end,
          verticalDirection: VerticalDirection.up,
          children: <Widget>[
            Text(
              " hello world ",
              style: TextStyle(fontSize: 30.0),
            ),
            Text(" I am yuexiaowei ")
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.end,
          verticalDirection: VerticalDirection.down,
          children: <Widget>[
            Text(
              " hello world ",
              style: TextStyle(fontSize: 30.0),
            ),
            Text(" I am yuexiaowei ")
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          verticalDirection: VerticalDirection.down,
          children: <Widget>[
            Text(
              " hello world ",
              style: TextStyle(fontSize: 30.0),
            ),
            Text(" I am yuexiaowei ")
          ],
        ),

        // Expanded(
        //   flex: 1,
        //   child: Container(color: Colors.red, width: 60),
        // ),
        // Container(color: Colors.blue, width: 80, height: 80),
        // Container(color: Colors.green, width: 70, height: 70),
        // Expanded(
        //   flex: 1,
        //   child: Container(color: Colors.orange, width: 100),
        // )
      ],
    );
  }
}

/**
 * 在开发中，我们多个组件很有可能需要重叠显示，比如在一张图片上显示文字或者一个按钮等。
在Android中可以使用Frame来实现，在Web端可以使用绝对定位，在Flutter中我们需要使用层叠布局Stack。

参数j解析：
alignment：此参数决定如何去对齐没有定位（没有使用Positioned）或部分定位的子widget。所谓部分定位，在这里**特指没有在某一个轴上定位：
**left、right为横轴，top、bottom为纵轴，只要包含某个轴上的一个定位属性就算在该轴上有定位。
textDirection：和Row、Wrap的textDirection功能一样，都用于决定alignment对齐的参考系即：textDirection的值为TextDirection.ltr，
则alignment的start代表左，end代表右；textDirection的值为TextDirection.rtl，则alignment的start代表右，end代表左。
fit：此参数用于决定没有定位的子widget如何去适应Stack的大小。StackFit.loose表示使用子widget的大小，StackFit.expand表示扩伸到Stack的大小。
overflow：此属性决定如何显示超出Stack显示空间的子widget，值为Overflow.clip时，超出部分会被剪裁（隐藏），值为Overflow.visible 时则不会。


**注意：**Positioned组件只能在Stack中使用。
 */
class MyHomeBodyStack extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Container(
          color: Colors.purple,
          width: 300,
          height: 300,
        ),
        Positioned(
            left: 20,
            top: 20,
            child: Icon(Icons.favorite, size: 50, color: Colors.white)),
        Positioned(
          bottom: 20,
          right: 20,
          child: Text("你好啊，李银河",
              style: TextStyle(fontSize: 20, color: Colors.white)),
        )
      ],
    );
  }
}
